package com.wky.user.service.impl;

import com.wky.basic.constant.SmsContants;
import com.wky.basic.exception.BusinessException;
import com.wky.basic.util.StrUtils;
import com.wky.basic.util.VerifyCodeUtils;
import com.wky.user.service.VerifyCodeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
public class VerifyCodeServiceImpl implements VerifyCodeService {

    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private JavaMailSender javaMailSender;

    /**
     * 获取验证码图片的base64编码
     *
     * @param key
     * @return
     */
    @Override
    public String verifyCodeImage(String key) {
        //1. 判断key是否存在
        if (key == null) {
            throw new BusinessException("key不能为空！");
        }
        //2. 生成一个随机的验证码
        String code = StrUtils.getRandomString(4);

        //3. 将验证码保存到redis中，并设置过期时间
        redisTemplate.opsForValue().set(key, code, 5, TimeUnit.MINUTES);

        //4. 将验证码图片进行base64编码
        String base64Img = VerifyCodeUtils.VerifyCode(100, 40, code);

        return base64Img;
    }

    /**
     * 发送手机验证码
     *
     * @param phoneMap
     * @return
     */
    @Override
    public String sendVerifyCode(Map<String, String> phoneMap) {

        //1. 获取手机号+图片验证码
        String phone = phoneMap.get("phone");
        String imageCodeKey = phoneMap.get("imageCodeKey");
        String imageCode = phoneMap.get("imageCode");
        //2. 非空判断+手机号正则表达式                                            @Todo
        if (phone == null || imageCode == null || imageCodeKey == null) {
            throw new BusinessException("手机号或图片验证码不能为空！");
        }
        //3. 根据imageKey获取redis中的图片验证码
        String redisImgCode = (String) redisTemplate.opsForValue().get(imageCodeKey);
        //4. 判断图片验证码是否正确
        if (!redisImgCode.equals(imageCode)) {
            throw new BusinessException("图片验证码错误！");
        }

        //1. 获取存手机验证码的key，value
        String key = String.format(SmsContants.VERIFY_CODE_KEY, phone);
        Map<String, String> value = (Map<String, String>) redisTemplate.opsForValue().get(key);
        //2. 非首次获取验证码，且有效期在1-5分钟内
        if (value != null) {
            //获取redis中的时间戳
            String timestamp = value.get("timestamp");
            //1分钟内
            if (System.currentTimeMillis() - Long.parseLong(timestamp) < 1 * 60 * 1000) {
                throw new BusinessException("1分钟内不能重复获取验证码！");
            }
            //1分钟到5分钟内
            if (System.currentTimeMillis() - Long.parseLong(timestamp) < 5 * 60 * 1000) {
                //获取code，刷新过期时间和时间戳
                String code = value.get("code");
                value.put("timestamp", String.valueOf(System.currentTimeMillis()));
                redisTemplate.opsForValue().set(key, value, 5, TimeUnit.MINUTES);
                //发送验证码
                return code;
            }
        }
        //3. 首次获取验证码或验证码已过期
        //生成一个随机的验证码
        String code = StrUtils.getRandomString(4);
        //获取当前时间戳
        String timestamp = String.valueOf(System.currentTimeMillis());
        Map<String, String> map = new HashMap<>();
        //存入map中
        map.put("timestamp", timestamp);
        map.put("code", code);
        //将code与timestamp存入redis中的一个key中
        redisTemplate.opsForValue().set(key, map, 5, TimeUnit.MINUTES);
        //发送验证码
        return code;
    }

    /**
     * 发送邮箱验证码
     * @param emailMap
     * @return
     */
    @Override
    public String emailVerifyCode(Map<String, String> emailMap) {
        //获取邮箱
        String email = emailMap.get("email");
        //判断邮箱是否为空
        if (email == null || email.equals("")) {
            throw new BusinessException("邮箱不可为空");
        }
        //判断邮箱格式
        if (!email.matches("^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$")) {
            throw new BusinessException("邮箱格式错误");
        }

        //1. 获取存邮箱验证码的key，value
        String key = String.format(SmsContants.EMAIL_VERIFY_CODE_KEY, email);
        Map<String, String> value = (Map<String, String>) redisTemplate.opsForValue().get(key);
        //2. 非首次获取验证码，且有效期在1-5分钟内
        if (value != null) {
            //获取redis中的时间戳
            String timestamp = value.get("timestamp");
            //1分钟内
            if (System.currentTimeMillis() - Long.parseLong(timestamp) < 1 * 60 * 1000) {
                throw new BusinessException("1分钟内不能重复获取验证码！");
            }
            //1分钟到5分钟内
            if (System.currentTimeMillis() - Long.parseLong(timestamp) < 5 * 60 * 1000) {
                //获取code，刷新过期时间和时间戳
                String code = value.get("code");
                value.put("timestamp", String.valueOf(System.currentTimeMillis()));
                redisTemplate.opsForValue().set(key, value, 5, TimeUnit.MINUTES);
                //发送邮箱验证码
                SimpleMailMessage mailMessage = new SimpleMailMessage();
                //设置发送人
                mailMessage.setFrom("1721582950@qq.com");
                //邮件主题
                mailMessage.setSubject("王凯悦大帅哥");
                //邮件内容
                mailMessage.setText(code);
                //收件人
                mailMessage.setTo(email);
                javaMailSender.send(mailMessage);
                return "发送成功";
            }
        }
        //3. 首次获取验证码或验证码已过期
        //生成一个随机的验证码
        String code = StrUtils.getRandomString(4);
        //获取当前时间戳
        String timestamp = String.valueOf(System.currentTimeMillis());
        Map<String, String> map = new HashMap<>();
        //存入map中
        map.put("timestamp", timestamp);
        map.put("code", code);
        //将code与timestamp存入redis中的一个key中
        redisTemplate.opsForValue().set(key, map, 5, TimeUnit.MINUTES);
        //发送验证码
        //发送邮箱验证码
        SimpleMailMessage mailMessage = new SimpleMailMessage();
        //设置发送人
        mailMessage.setFrom("1721582950@qq.com");
        //邮件主题
        mailMessage.setSubject("王凯悦大帅哥");
        //邮件内容
        mailMessage.setText(code);
        //收件人
        mailMessage.setTo(email);
        javaMailSender.send(mailMessage);
        return "发送成功";
    }

}

